﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EpidemicSimulator.strategies;
using EpidemicSimulator.stopconditions;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using GraphInformation;

namespace EpidemicSimulator
{
    public class SimulationSetup
    {
        public int condition;

        public Graph networkGraph { get; set; }

        public String networkGraphML { get; set; }

        public String diseaseModelGraphML { get; set; }
        
        public StateChangePlanSL[] stateChangePlansSL {
            set
            {
                foreach (StateChangePlanSL s in value)
                {
                    StateChangePlan stateChangePlan = null;

                    StateChangeStrategy strategy = (StateChangeStrategy)getInstance(s.stateChangeStrategyName);
                    if (s.inPersents)
                    {
                        stateChangePlan = new PersentageStateChangePlan(s.value, strategy, s.applyTime);
                    }
                    else
                    {
                        stateChangePlan = new NumericalStateChangePlan(s.value, strategy, s.applyTime);
                    }
                    stateChangePlans.Add(stateChangePlan);
                }
            }
        }

        public List<StateChangePlan> stateChangePlans { get; set; }

        public int maxContactsPerStep { get; set; }
        public int minContactsPerStep { get; set; }

        public StopConditionSL[] stopConditionsSL
        {
            set
            {
                foreach (StopConditionSL s in value)
                {
                    Type type = Type.GetType(s.stopConditionName, true);
                    object newInstance = Activator.CreateInstance(type, s.initParams);
                    this.addStopCondition((StopCondition)newInstance);
                }
            }
        }

        public List<StopCondition> stopConditions { get; set; }

        public SimulationSetup()
        {
            stateChangePlans = new List<StateChangePlan>();
            stopConditions = new List<StopCondition>();
        }

        public SimulationSetup(String networkGraphML, String diseaseModelGraphML, int maxContactsPerStep, int minContactsPerStep)
        {
            this.networkGraphML = networkGraphML;
            this.diseaseModelGraphML = diseaseModelGraphML;
            this.maxContactsPerStep = maxContactsPerStep;
            this.minContactsPerStep = minContactsPerStep;
            stateChangePlans = new List<StateChangePlan>();
            stopConditions = new List<StopCondition>();
        }

        public void addStateChangePlan(StateChangePlan plan)
        {
            stateChangePlans.Add(plan);
        }

        public void addStopCondition(StopCondition stopCondition)
        {
            stopConditions.Add(stopCondition);
        }

        private static Object getInstance(string className)
        {
            Type type = Type.GetType(className, true);
            object newInstance = Activator.CreateInstance(type);
            return newInstance;
        }
    }

    [DataContract]
    public class SimulationSetupSL
    {
        [DataMember]
        public String networkGraphML { get; set; }

        [DataMember]
        public String diseaseModelGraphML { get; set; }

        [DataMember]
        public Graph networkGraph { get; set; }

        [DataMember]
        public StateChangePlanSL[] stateChangePlansSL { get; set; }

        [DataMember]
        public int maxContactsPerStep { get; set; }

        [DataMember]
        public int minContactsPerStep { get; set; }

        [DataMember]
        public int condition { get; set; }

        [DataMember]
        public StopConditionSL[] stopConditionsSL { get; set; }
    }

    [DataContract]
    public class StateChangePlanSL
    {
        [DataMember]
        public string stateChangeStrategyName { get; set; }

        [DataMember]
        public long applyTime { get; set; }

        [DataMember]
        public int value { get; set; }

        [DataMember]
        public bool inPersents { get; set; }
    }

    [DataContract]
    public class StopConditionSL
    {
        [DataMember]
        public string stopConditionName { get; set; }

        [DataMember]
        public object[] initParams { get; set; }
    }
}
